package com.bestcem.xm.award.dao.impl.mysql;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Validator;
import com.bestcem.xm.award.constant.Constants;
import com.bestcem.xm.award.constant.RedisKeyConstant;
import com.bestcem.xm.award.dao.AwardRequestDao;
import com.bestcem.xm.award.dao.mapper.AwardRequestMapper;
import com.bestcem.xm.award.dao.mapper.query.RequestQuery;
import com.bestcem.xm.award.entity.mysql.AwardRequestEntity;
import com.bestcem.xm.award.entity.pojo.AwardRequestDO;
import com.bestcem.xm.award.enums.AwardRequestStatusEnum;
import com.bestcem.xm.award.lua.IncreaseAwardRequestCountLua;
import com.bestcem.xm.award.service.dto.awardaward.GetRequestStatsDTO;
import com.bestcem.xm.common.core.uitls.DateUtil;
import com.bestcem.xm.common.core.uitls.StringUtil;
import com.bestcem.xm.componet.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;

import static com.bestcem.xm.award.enums.AwardRequestStatusEnum.PASS;

/**
 * AWARD_REQUEST表
 *
 * @author jie.yao <jie.yao@idiaoyan.com>
 * @version v1.0
 * @date 2021/6/30 16:50
 */
@Repository
@Slf4j
public class AwardRequestDaoImpl implements AwardRequestDao {

    @Resource
    private AwardRequestMapper awardRequestMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IncreaseAwardRequestCountLua increaseAwardRequestCountLua;

    @Override
    public AwardRequestDO insert(AwardRequestDO awardRequestDO) {
        AwardRequestEntity entity = toEntity(awardRequestDO);
        String id = StringUtil.getId();
        entity.setRequestId(id);
        entity.setCreateTime(DateUtil.getCommonDate());
        entity.setUpdateTime(DateUtil.getCommonDate());
        awardRequestMapper.insert(entity);
        addRequestCount(awardRequestDO.getAwardId(), 1, awardRequestDO.getStatus() == PASS.getIndex() ? 1 : 0);
        return findById(entity.getRequestId());
    }

    @Override
    public AwardRequestDO findById(String requestId) {
        AwardRequestEntity entity = awardRequestMapper.getById(requestId);
        return toDO(entity);
    }

    /**
     * 更新请求状态
     *
     * @param requestId 请求id
     * @param status    原有奖励请求状态
     * @param awardId   查询条件 奖励id
     * @param newStatus 待更新的奖励请求状态
     * @return 返回原数据
     */
    @Override
    public AwardRequestDO findAndModify(String requestId, AwardRequestStatusEnum status, String awardId, AwardRequestStatusEnum newStatus) {
        awardRequestMapper.updateStatusByIdAndAwardIdAndStatus(requestId, status.getIndex(), awardId, newStatus.getIndex(), DateUtil.getCommonDate());
        addRequestCount(awardId, 0, newStatus.getIndex() == PASS.getIndex() ? 0 : -1);
        return findById(requestId);
    }

    /**
     * 增加请求统计
     * @param awardId 奖励id
     * @param total 总请求数量增加
     * @param pass  总通过数量增加
     */
    public void addRequestCount(String awardId, int total, int pass) {
        if (log.isInfoEnabled()) {
            log.info("[award] addRequestCount: total:{},pass:{}", total, pass);
        }
        String requestKey = String.format(RedisKeyConstant.AWARD_COUNT_REQUEST, awardId);
        String today = cn.hutool.core.date.DateUtil.today();
        String requestDayKey = String.format(RedisKeyConstant.AWARD_COUNT_DAY_REQUEST, awardId, today);
        Object execute = redisService.execute(increaseAwardRequestCountLua.getRedisScript(), Arrays.asList(requestKey, requestDayKey), total, pass);
        if (log.isInfoEnabled()) {
            log.info("[award] addRequestCount reslut: total:{},pass:{}, result:{}", total, pass, execute);
        }
    }

    @Override
    public long countAwardRequestBySurveySeqAndDeliverId(Long surveySeq, String deliverId) {
        Assert.notNull(surveySeq, "答卷标识不能为空");
        RequestQuery requestQuery = new RequestQuery();
        requestQuery.setDeliverId(deliverId);
        requestQuery.setSurveySeq(surveySeq);
        return awardRequestMapper.countByConditions(requestQuery);
    }

    @Override
    public long countAwardRequestByAwardRequest(AwardRequestDO awardRequestDO) {
        RequestQuery requestQuery = createQuery(awardRequestDO);
        return awardRequestMapper.countByConditions(requestQuery);
    }

    private RequestQuery createQuery(AwardRequestDO awardRequestDO) {
        Assert.notNull(awardRequestDO, "查询条件不能为空");
        RequestQuery requestQuery = new RequestQuery();
        requestQuery.setAwardId(awardRequestDO.getAwardId());
        // status
        if (Validator.isNotNull(awardRequestDO.getStatus())) {
            requestQuery.setStatus(awardRequestDO.getStatus());
        }
        // deliver.deliver_id
        String deliverDeliverId = Optional.of(awardRequestDO).map(AwardRequestDO::getDeliverDTO)
                .map(AwardRequestDO.Deliver::getDeliverId).orElse(Constants.BLANK);
        if (StringUtils.isNotBlank(deliverDeliverId)) {
            requestQuery.setDeliverId(deliverDeliverId);
        }
        // deliver.memberId
        String deliverMemberId = Optional.of(awardRequestDO).map(AwardRequestDO::getDeliverDTO)
                .map(AwardRequestDO.Deliver::getMemberId).orElse(Constants.BLANK);
        if (StringUtils.isNotBlank(deliverMemberId)) {
            requestQuery.setMemberId(deliverMemberId);
        }
        // ip
        String remoteIp = awardRequestDO.getIp();
        if (StringUtils.isNotBlank(remoteIp)) {
            requestQuery.setIp(remoteIp);
        }
        return requestQuery;
    }

    @Override
    public GetRequestStatsDTO getRequestCount(String awardId, String deliverId) {
        GetRequestStatsDTO getRequestStatsDTO = new GetRequestStatsDTO();
        RequestQuery requestQuery = new RequestQuery();
        requestQuery.setAwardId(awardId);
        if (StringUtils.isNotBlank(deliverId)) {
            requestQuery.setDeliverId(deliverId);
        }
        Integer totalCount = awardRequestMapper.countByConditions(requestQuery);
        getRequestStatsDTO.setTotalCount(totalCount);
        requestQuery.setStatus(PASS.getIndex());
        Integer passCount = awardRequestMapper.countByConditions(requestQuery);
        getRequestStatsDTO.setPassCount(passCount);
        return getRequestStatsDTO;
    }

    @Override
    public GetRequestStatsDTO getRequestCountDay(String awardId, String deliverId, Date day) {
        GetRequestStatsDTO getRequestStatsDTO = new GetRequestStatsDTO();
        RequestQuery requestQuery = new RequestQuery();
        requestQuery.setAwardId(awardId);
        if (StringUtils.isNotBlank(deliverId)) {
            requestQuery.setDeliverId(deliverId);
        }
        DateTime dateTime = new DateTime(day);
        requestQuery.setDay(dateTime);
//        Integer totalCount = awardRequestMapper.countByConditions(requestQuery);
//        getRequestStatsDTO.setTotalCount(totalCount);
//        requestQuery.setStatus(PASS.getIndex());
//        Integer passCount = awardRequestMapper.countByConditions(requestQuery);
//        getRequestStatsDTO.setPassCount(passCount);
        getRequestStatsDTO = awardRequestMapper.selectTotalCountAndPassCount(requestQuery);

        return getRequestStatsDTO;
    }

    /**
     * entity -> DO
     *
     * @param entity 奖励请求entity
     * @return 奖励请求DO
     */
    private AwardRequestDO toDO(AwardRequestEntity entity) {
        AwardRequestDO awardRequestDO = new AwardRequestDO();
        awardRequestDO.setId(entity.getRequestId());
        awardRequestDO.setAwardId(entity.getAwardId());
        awardRequestDO.setIp(entity.getIp());
        awardRequestDO.setStatus(entity.getStatus());
        awardRequestDO.setTty(entity.getDeviceType());
        awardRequestDO.setDeliver(entity.getDeliver());
        AwardRequestDO.Survey survey = new AwardRequestDO.Survey();
        survey.setSurveyId(entity.getSurvey().getSurveyId());
        survey.setSeq(entity.getSurvey().getSeq());
        survey.setStatus(entity.getSurvey().getStatus());
        survey.setSource(entity.getSurvey().getSource());
        survey.setSurveyIp(entity.getSurvey().getSurveyIp());
        survey.setTs(entity.getSurvey().getTs());
        survey.setDeliverId(entity.getSurvey().getDeliverId());
        survey.setCostTime(entity.getSurvey().getCostTime());
        survey.setSig(entity.getSurvey().getSig());
        awardRequestDO.setSurvey(survey);
        return awardRequestDO;
    }

    /**
     * DO -> entity
     *
     * @param awardRequestDO DO
     * @return entity
     */
    private AwardRequestEntity toEntity(AwardRequestDO awardRequestDO) {
        AwardRequestEntity entity = new AwardRequestEntity();
        entity.setAwardId(awardRequestDO.getAwardId());
        entity.setIp(awardRequestDO.getIp());
        entity.setStatus(awardRequestDO.getStatus());
        entity.setDeviceType(awardRequestDO.getTty());
        entity.setDeliver(awardRequestDO.getDeliver());
        AwardRequestEntity.Survey survey = new AwardRequestEntity.Survey();
        survey.setSurveyId(awardRequestDO.getSurvey().getSurveyId());
        survey.setSeq(awardRequestDO.getSurvey().getSeq());
        survey.setStatus(awardRequestDO.getSurvey().getStatus());
        survey.setSource(awardRequestDO.getSurvey().getSource());
        survey.setSurveyIp(awardRequestDO.getSurvey().getSurveyIp());
        survey.setTs(awardRequestDO.getSurvey().getTs());
        survey.setDeliverId(awardRequestDO.getSurvey().getDeliverId());
        survey.setCostTime(awardRequestDO.getSurvey().getCostTime());
        survey.setSig(awardRequestDO.getSurvey().getSig());
        entity.setSurvey(survey);
        return entity;
    }
}
